// VITE_API_BASE_URL= 'http://43.139.215.142:8081'
// VITE_WS_BASE_URL= 'ws://43.139.215.142:8081'
VITE_API_BASE_URL= 'http://127.0.0.1:8081'
VITE_WS_BASE_URL= 'ws://127.0.0.1:8081'

let pc = null;
let pendingCandidates = [];
let remoteDescSet = false;

const inviteCodeFormRef = document.getElementById("inviteCodeForm")
const videoContainerRef = document.getElementById("videoContainer")
const phoneBoxRef = document.getElementById("phoneBox")
const rttRef = document.getElementById("rtt")
const resetControlRef = document.getElementById("resetControl")
const resetControlBtnRef = document.getElementById("resetControlBtn")
let videoRef = null

document.querySelector('.form-card').addEventListener('submit', function (e) {
    console.log("触发了")
  e.preventDefault(); // ✅ 阻止页面刷新！
  const code = document.getElementById('inviteCode').value.trim();

  if (code.length !== 6 || !/^\d{6}$/.test(code)) {
    alert("请输入6位数字的投屏码");
    return;
  }
  console.log("提交邀请码:", code); // 用于调试，确认是否触发
  startJoin(code)
});

// 雪花 ID 生成器（简化版）
const generateSnowflakeId = () => {
  const timestamp = BigInt(Date.now()); // 毫秒时间戳
  const random = BigInt(Math.floor(Math.random() * 1000000)); // 随机部分（模拟机器ID+序列号）
  const snowflakeId = (timestamp << 20n) | random; // 拼接：时间戳 << 20 | 随机
  return snowflakeId.toString(); // 返回字符串形式
}

const throttle = (fn, delay) => {
  let lastTime = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastTime >= delay) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
}


let browserUniqueId = "";
browserUniqueId = localStorage.getItem('browser_unique_id');

if (browserUniqueId) {
    console.log('浏览器指纹（缓存）:', browserUniqueId);
} else {
    browserUniqueId = generateSnowflakeId()
    localStorage.setItem('browser_unique_id', browserUniqueId);
    console.log('浏览器指纹（新生成）:', browserUniqueId);
}

const signalingServerUrl = `${VITE_WS_BASE_URL}/caller/websocket?BrowserId=${browserUniqueId}`;
const ws = new WebSocket(signalingServerUrl);

const startJoin = (inviteCode) => {
    ws.send(JSON.stringify({ type: 'join', data: inviteCode }));
};

const sendOpr = (opr) => {
    ws.send(JSON.stringify({ type: 'opr', data: opr }));
}

const startWebRTC = async () => {
    // 关闭输入同时展示video
    inviteCodeFormRef.style.display = 'none'
    phoneBoxRef.style.display = 'none'
    videoContainerRef.style.display = 'flex'
    rttRef.style.display = 'block'
    resetControlRef.style.display = 'block'
    videoRef = document.getElementById("screen")
    pc = new RTCPeerConnection({
      iceTransportPolicy: "all", // 默认就是 all，relay 会限制候选，只用 TURN
      iceServers: [
        {
          urls: 'turn:stun.zhikayun.com:3478',
          username: 'admin',
          credential: '123456'
        },
        // {
        //   urls: 'stun:stun.l.google.com:19302'
        // }
      ]
    });

    pc.onicecandidate = (event) => {
      if (event.candidate) {
        console.log('local:', event.candidate.candidate);
        ws.send(JSON.stringify({ type: 'ice', data: event.candidate }));
      } else {
        console.log('All ICE candidates have been sent');
      }
    };

    pc.oniceconnectionstatechange = () => {
      console.log('ICE Connection State:', pc.iceConnectionState);
      if (pc.iceConnectionState === 'connected') {
        // 等连接稳定后再获取 stats
      }
    };

    pc.onicecandidateerror = (event) => {
      console.error('ICE Candidate Error:', event);
    };

    pc.ontrack = (event) => {
        console.log("获取到了流")
        videoRef.srcObject = event.streams[0]
        // event.streams[0].getVideoTracks()[0].addEventListener('mute', () => {
        //   console.warn("视频轨道被 mute 了");
        // });
        // event.streams[0].getVideoTracks()[0].addEventListener('ended', () => {
        //   console.warn("视频轨道结束了");
        // });
        videoRef.onloadedmetadata = () => {
            // videoRef.style.height = "auto"
            // videoRef.style.width = "100%"
            console.log("解析完毕")
            videoRef.play()
        }
    };

    pc.addTransceiver('video', { direction: 'recvonly' });

    // const offer = await pc.createOffer();
    // await pc.setLocalDescription(offer);
    // ws.send(JSON.stringify({ type: 'sdp', data: offer }));
};


ws.onopen = () => {
    console.log('WebSocket 已连接');
};

ws.onclose = () => {
    console.log("Websocket 已关闭")
}

ws.onerror = () => {
}

ws.onmessage = async (event) => {
    const msg = JSON.parse(event.data);
    switch (msg.type) {
        case 'feedback':{
            if (msg.code === 200) {
                
            } else {
                Message.warning(msg.data)
            }
            break;
        }
        case 'sdp':{
            startWebRTC();
            const remoteDesc = new RTCSessionDescription(msg.data);
            await pc.setRemoteDescription(remoteDesc);
            // console.log("设置了远端 SDP");

            // 创建 answer 并发送
            const answer = await pc.createAnswer();
            await pc.setLocalDescription(answer);
            ws.send(JSON.stringify({ type: 'sdp', data: answer }));

            remoteDescSet = true;

            // 添加之前缓存的 ICE
            pendingCandidates.forEach(candidate => {
                pc.addIceCandidate(new RTCIceCandidate(candidate));
            });
            pendingCandidates = [];
            break;
        }
        case 'ice':{
            const candidate = new RTCIceCandidate(msg.data);
            if (remoteDescSet) {
                await pc.addIceCandidate(candidate);
            } else {
                pendingCandidates.push(candidate);
            }
            break;
        }
        // 该分支主要是对 失败条件进行判断
        case 'oprcallback':{
            Message.warning(msg.data.msg)
            break;
        }
        case 'orientation':{
            orientationCallback(msg.data)
            break;
        }
        default:{
            break;
        }
        
    }
};

let rotation = 0

const orientationCallback = (data) => {
    [shortSide, longSide] = data.width > data.height?[data.height,data.width]:[data.width, data.height]
    rotation = data.rotation
    console.log(rotation%2)
    if (rotation % 2 === 0){
        videoContainerRef.style.width = '294px'
        videoContainerRef.style.height = '661px'
        videoRef.style.width = 'auto'
        videoRef.style.height = '100%'

    } else {
        videoContainerRef.style.width = '661px'
        videoContainerRef.style.height = '294px'
        videoRef.style.width = '100%'
        videoRef.style.height = 'auto'
    }
}

const getCurrentRTT = async () => {
    const stats = await pc.getStats();
    let selectedCandidatePairId = null;

    stats.forEach((report) => {
        if (report.type === 'transport') {
        selectedCandidatePairId = report.selectedCandidatePairId;
        }
    });

    stats.forEach((report) => {
        if (report.id === selectedCandidatePairId && report.currentRoundTripTime) {
        const rtt = report.currentRoundTripTime;
        // console.log(`延迟:${(rtt * 1000).toFixed(2)}`)
        
        rttRef.innerText = `延迟:${(rtt * 1000).toFixed(2)}ms`
        }
    });
};

let rttInterval = setInterval(() => {
    if (pc) getCurrentRTT();
}, 3000);

const closeWebrtc = () => {
    if (pc) {
        // pc.getSenders().forEach(sender => pc.removeTrack(sender)); // 移除所有 track
        pc.close();     // 正式关闭连接
        pc = null;      // 清除引用，避免内存泄漏
        clearInterval(rttInterval);
        console.log("PeerConnection 已关闭");
    }
    if (rttInterval) {
        clearInterval(rttInterval);
        rttInterval = null;
        console.log("RTT 定时器已清除");
    }
}

const closeConnection = () => {
    ws.close()
    ws = null;
    closeWebrtc()
}



/**
 * 
 * 控制模块
 * 
 */
const PRESS_THRESHOLD = 500 // ms
const BUFFER_DELAY = 100        // ms

let shortSide = 600
let longSide = 980

let keyPressStartTime = {}
let keyInputBuffer = ''
let keyBufferTimer = null

let isLongPress = false
let isPressSlide = false
let startPoint = { x: 0, y: 0 }
let currentPoint = { x: 0, y: 0 }
let longPressTimer = null

const analyseShortcutKey = (ctrlPressed, pressedKey) => {
  let order = ''
  if (ctrlPressed) {
    switch (pressedKey) {
      case 'h': order = 'keyboard/home'; break
      case 'o': order = 'keyboard/recent'; break
      case 'b': order = 'keyboard/back'; break
      case 'c': order = 'keyboard/copy'; break
      case 'v': order = 'keyboard/paste'; break
      case 'r': order = 'keyboard/release'; break
      default: return
    }
  } else if (pressedKey === 'enter') {
    order = 'keyword/enter'
  }

  if (order) {
    ws.send(JSON.stringify({ type: 'opr', data: order }))
  }
}
const handleKeyDown = (e) => {
  const key = e.key.toLowerCase()

  if ((e.ctrlKey && ['c', 'v', 'h', 'o', 'b', 'r'].includes(key)) || key === 'enter') {
    e.preventDefault()
    analyseShortcutKey(e.ctrlKey, key)
    return
  }

  // 防止重复记录按下（处理 keydown 重复）
  if (!(key in keyPressStartTime)) {
    keyPressStartTime[key] = Date.now()
  }
}

const handleKeyUp = (e) => {
  const key = e.key.toLowerCase()
  console.log(e)
  // 如果这个键是组合键中已经处理过的，忽略它
  if (e.ctrlKey || key === 'control' || key === 'enter') {
    delete keyPressStartTime[key]
    return
  }

  const startTime = keyPressStartTime[key]
  delete keyPressStartTime[key]
  if (!startTime) return

  const pressDuration = Date.now() - startTime

  if (pressDuration >= PRESS_THRESHOLD) {
    // 长按
    ws.send(JSON.stringify({ type: 'opr', data: `keyboard/press?key=${key}` }))
  } else {
    // 短按（write 立即发送）
    ws.send(JSON.stringify({ type: 'opr', data: `keyboard/write?key=${key}` }))
  }
}

const ratePositionComputed = (e) => {
    console.log(shortSide, longSide)
  const shortRate = (shortSide/longSide)
  if ([0,1].includes(rotation)){
    const nowx = e.x
    const nowy = e.y
    const cmpdWidth = Math.floor(shortSide/(shortRate*661)*nowx)
    const cmpdHeight = Math.floor(longSide/661*nowy)
    return {x:cmpdWidth, y:cmpdHeight}
  } 
    const nowx = 661 - e.x
    const nowy = (shortRate*661) - e.y
    const cmpdHeight = Math.floor(shortSide/(shortRate*661)*nowy)
    const cmpdWidth = Math.floor(longSide/661*nowx)
    return {x:cmpdWidth, y:cmpdHeight}
}
let occurMouse = false
let moveCount = 0
const isDistanceEnough = (start, end, threshold = 5) => {
  const dx = end.x - start.x
  const dy = end.y - start.y
  return Math.sqrt(dx * dx + dy * dy) > threshold
}

// 触发两次才算是触发了长触摸事件
const handleMouseDown = (e) => {
  const div = videoContainerRef
  if (!div) return
  occurMouse = true
  const rect = div.getBoundingClientRect()
  if (
    e.clientX < rect.left ||
    e.clientX > rect.right ||
    e.clientY < rect.top ||
    e.clientY > rect.bottom
  ) {
    // 鼠标移出了 wrapper 区域
    // 可以阻止操作或模拟锁定
    // console.log('鼠标已移出区域')
    return
    // 可选做法：设置鼠标样式或忽略拖拽逻辑等
  } 
  const x = e.clientX - rect.left
  const y = e.clientY - rect.top
  startPoint = { x, y }
  currentPoint = { ...startPoint }

  // 启动长按定时器（比如 500ms）
  longPressTimer = setTimeout(() => {
    if (startPoint.x === currentPoint.x && startPoint.y === currentPoint.y){
      isLongPress = true
      console.log('长按触发')
      const dt = ratePositionComputed(currentPoint)
    //   emits('oprcallback', `mouse/press?x=${dt.x}&y=${dt.y}`)
    sendOpr(`mouse/press?x=${dt.x}&y=${dt.y}`);
    
    }
    // 可以触发自定义长按事件
  }, 500)

}
// 能进这里的就不是滑动事件
const handleMouseMove = throttle((e) => {
  if (!occurMouse) return
  if (moveCount < 3) {
    moveCount+=1
    // 如果移动次数超过10次，认为是滑动事件
    return
  }
  const div = videoContainerRef
  if (!div) return

  const rect = div.getBoundingClientRect()
  const x = e.clientX - rect.left
  const y = e.clientY - rect.top
  currentPoint = { x, y }
  if (isLongPress === true || startPoint.x <= 0) {
    return
  }
  if (
    e.clientX < rect.left ||
    e.clientX > rect.right ||
    e.clientY < rect.top ||
    e.clientY > rect.bottom
  ) {
    // 鼠标移出了 wrapper 区域
    // 可以阻止操作或模拟锁定
    // console.log('鼠标已移出区域')
    return
    // 可选做法：设置鼠标样式或忽略拖拽逻辑等
  } 
  if (isPressSlide === false){
    clearInterval(longPressTimer)
    isPressSlide = true
    console.log("手机触摸按下事件")
    const dt = ratePositionComputed(currentPoint)
    // emits('oprcallback', `mouse/down?x=${dt.x}&y=${dt.y}`)
    sendOpr(`mouse/down?x=${dt.x}&y=${dt.y}`);
    return
  }

  const dt1 = ratePositionComputed(currentPoint)
//   emits('oprcallback', `mouse/move?x=${dt1.x}&y=${dt1.y}`)
sendOpr(`mouse/move?x=${dt1.x}&y=${dt1.y}`);
  console.log('鼠标移动:', currentPoint)
}, 100)  // 每 50ms 执行一次

const handleMouseUp = (e) => {
  const tempMoveCount = moveCount
  moveCount = 0
  if (!occurMouse) return
  occurMouse = false
  const div = videoContainerRef
  if (!div) return
  const rect = div.getBoundingClientRect()
  let x
  let y
  if (
    e.clientX < rect.left ||
    e.clientX > rect.right ||
    e.clientY < rect.top ||
    e.clientY > rect.bottom
  ) {
    // 鼠标移出了 wrapper 区域
    // console.log('鼠标已移出区域')
    if (e.clientX < rect.left) {
      x = 0
    } else if (e.clientX > rect.right) {
      x = rect.width
    } else {
      x = e.clientX - rect.left
    }

    if (e.clientY < rect.top) {
      y = 0
    } else if (e.clientY > rect.bottom) {
      y = rect.height
    } else {
      y = e.clientY - rect.top
    }

  } else {
    // 鼠标在区域内，正常计算坐标
    x = e.clientX - rect.left
    y = e.clientY - rect.top
  }
  currentPoint = { x, y }
  if (longPressTimer) {
    clearTimeout(longPressTimer)
    longPressTimer = null
  }
  if (isLongPress === true){
    isLongPress = false
    // emits('oprcallback', `mouse/release`)
    sendOpr(`mouse/release`);
  } else if(isPressSlide ===true && tempMoveCount >= 4){
    isPressSlide = false
      console.log('鼠标触摸抬起事件', { x, y })
      const dt = ratePositionComputed(currentPoint)
    //   emits('oprcallback', `mouse/up?x=${dt.x}&y=${dt.y}`)
    sendOpr(`mouse/up?x=${dt.x}&y=${dt.y}`);
  } else if (isDistanceEnough(startPoint, currentPoint)) {
  // 判定为滑动
  console.log('鼠标滑动事件', { x, y })
  const dt = ratePositionComputed(startPoint)
  const dt1 = ratePositionComputed(currentPoint)
  sendOpr(`mouse/swipe1?x=${dt.x}&y=${dt.y}&ex=${dt1.x}&ey=${dt1.y}&s=10&d=300`);
//   emits('oprcallback', `mouse/swipe?x=${dt.x}&y=${dt.y}&ex=${dt1.x}&ey=${dt1.y}`)
} else {
  // 点击
  console.log('鼠标点击事件', rotation, { x, y })
  const dt = ratePositionComputed(currentPoint)
  sendOpr(`mouse/click?x=${dt.x}&y=${dt.y}`);
//   emits('oprcallback', `mouse/click?x=${dt.x}&y=${dt.y}`)
}
  startPoint = {x:0}
  currentPoint = {x:0}
}

const handleGlobalMouseUp = (e) => {
  handleMouseUp(e)  // 复用你原来的 handleMouseUp
}

const Message = {
    warning(text, duration = 3000) {
    const container = document.getElementById('message-container');
    const message = document.createElement('div');
    message.className = 'message';
    message.textContent = text;

    container.appendChild(message);

    // 自动移除
    setTimeout(() => {
        message.style.opacity = 0;
        setTimeout(() => {
        container.removeChild(message);
        }, 300);
    }, duration);
    }
};

videoContainerRef.addEventListener('mousemove', handleMouseMove)
videoContainerRef.addEventListener('mousedown', handleMouseDown)
videoContainerRef.addEventListener('mouseup', handleMouseUp)
window.addEventListener("keydown", handleKeyDown)
window.addEventListener("keyup",handleKeyUp)
resetControlBtnRef.addEventListener('click', function(){
    sendOpr("device/connect")
    sendOpr("keyboard/release")
})